package com.zimin.cloud.user.common.util;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.zimin.common.exception.GraceException;
import com.zimin.common.utils.RSAUtil;
import com.zimin.shared.enums.ResponseStatusEnum;

import java.util.Calendar;
import java.util.Date;

/**
 * jwt token 工具类
 *
 * @author 恒利
 * @since 2022/6/21 12:03 PM
 */
public class TokenUtil {

    private static final String ISSUER = "签发者";

    /**
     * <p>生成令牌</p>
     *
     * @param userId
     * @return java.lang.String
     * @since 2022-06-21 12:10:43
     */
    public static String generateToken(String userId) throws Exception {
        var algorithm = Algorithm.RSA256(RSAUtil.getPublicKey(), RSAUtil.getPrivateKey());
        var instance = Calendar.getInstance();
        instance.setTime(new Date());
        instance.add(Calendar.SECOND, 30);
        return JWT.create().withKeyId(userId).withIssuer(ISSUER).withExpiresAt(instance.getTime()).sign(algorithm);
    }

    /**
     * <p>
     *    校验token
     *    为什么token在生成时是抛出异常，在校验时是try-catch异常?
     *
     *    在校验token时可能会是多个地方，如果用户在操作的时候token过期，抛出指定的错误码，前端接收到参数之后就可以做一些特殊的操作了
     * </p>
     *
     * @param token
     * @return java.lang.String
     * @since 2022-06-21 12:14:50
     */
    public static String verifyToken(String token) {
        String userId = "";
        try {
            var algorithm = Algorithm.RSA256(RSAUtil.getPublicKey(), RSAUtil.getPrivateKey());
            var verifier = JWT.require(algorithm).build();
            var verify = verifier.verify(token);
            userId = verify.getKeyId();
        } catch (TokenExpiredException e) {
            GraceException.display(ResponseStatusEnum.TOKEN_IS_EXPIRED);
        } catch (Exception e){
            GraceException.display(ResponseStatusEnum.TOKEN_IS_ERROR);
        }
        return userId;
    }

    public static String generateRefreshToken(String userId) throws Exception {
        var algorithm = Algorithm.RSA256(RSAUtil.getPublicKey(), RSAUtil.getPrivateKey());
        var instance = Calendar.getInstance();
        instance.setTime(new Date());
        instance.add(Calendar.DAY_OF_WEEK, 7);
        return JWT.create().withKeyId(userId).withIssuer(ISSUER).withExpiresAt(instance.getTime()).sign(algorithm);
    }
}
